/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.alag.ci.blog.search.Impl;
import com.alag.ci.blog.search.*;
import com.alag.ci.blog.search.BlogQueryParameter.*;
import java.util.*;
import java.io.*;
import java.net.URLEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.*;
import org.xml.sax.SAXException;
import org.apache.http.client.*;
import org.apache.http.*;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.*;
import org.apache.http.client.params.HttpClientParams;
import org.xml.sax.helpers.DefaultHandler;

/**
 *
 * @author Justina
 */
public abstract class BlogSearcherImpl implements BlogSearcher {
    
    private static final String JAXP_PROPERTY_NAME = "javax.xml.parsers.SAXParserFactory";
    private static final String APACHE_XERCES_SAX_PARSER = "org.apache.xerces.jaxp.SAXParserFactory";
    private SAXParser parser = null;
    private Map<QueryParameter, String> paramStringMap = null;    
    
    public BlogSearcherImpl() throws BlogSearcherException {
        crateSAXParser();
        initializeParameterStringMap();
    }

    public BlogQueryResult getRelevantBlogs(BlogQueryParameter param) throws BlogSearcherException {
        BlogQueryResult result = new NullBlogQueryResultImpl();
        HttpClient client = new DefaultHttpClient();
        HttpUriRequest request = getRequest(param);
        try {
            HttpResponse response = client.execute(request);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                InputStream is = response.getEntity().getContent();
                result = parseContent(is);
                is.close();
            }
        }
        catch (ClientProtocolException ce) {
            throw new BlogSearcherException("HTTP exception", ce);
        }
        catch (IOException ioe) {
            throw new BlogSearcherException("IOException while getting response body", ioe);
        } 
        return result;
    }

    private void crateSAXParser() throws BlogSearcherException {
        if (System.getProperty(JAXP_PROPERTY_NAME) == null) {
            System.setProperty(JAXP_PROPERTY_NAME, APACHE_XERCES_SAX_PARSER);
        }
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            this.parser = factory.newSAXParser();
        } catch (ParserConfigurationException e) {
            throw new BlogSearcherException("SAX parser not found", e);
        } catch (SAXException se) {
            throw new BlogSearcherException("SAX exception", se);
        }        
    }

    private void initializeParameterStringMap() {
        paramStringMap = new EnumMap<QueryParameter, String>(QueryParameter.class);
    }
    
    protected Map<QueryParameter, String> getParamStringMap() {
        return paramStringMap;
    }
    
    protected SAXParser getSAXParser() {
        return this.parser;
    }

    protected abstract HttpUriRequest getRequest(BlogQueryParameter param);
    protected abstract BlogSearcherResponseHandler getBlogSearcherResponseHandler();

    private BlogQueryResult parseContent(InputStream is) throws BlogSearcherException {
        try {
            BlogSearcherResponseHandler h = getBlogSearcherResponseHandler();
            this.getSAXParser().parse(is, (DefaultHandler) h);
            return h.getBlogQueryResult();
        }
        catch (SAXException se) {
            throw new BlogSearcherException("Error parsing Response XML", se);
        }
        catch (IOException ioe) {
            throw new BlogSearcherException("IOException while parsing XML", ioe);
        }
    }

    public static String urlEncode(String s) {
        String result = s;
        try {
            result = URLEncoder.encode(s, "UTF-8");
        }
        catch (UnsupportedEncodingException e) {
            System.out.println("Unsupported encoding exception thrown");
        }
        return result;
    }
    
}
